import { _decorator, Component, Enum, EventHandler, EventTouch, Node, ScrollView, Size, UITransform, v3 } from 'cc';
import { ListLayerData, ListRender } from './ListRender';
import { PoolFactory } from './PoolFactory';
const { ccclass, property, menu } = _decorator;

/**列表排列方式 */
enum ListType {
  /**水平排列 */
  Horizontal,
  /**垂直排列 */
  Vertical,
}
Enum(ListType);

/**列表对齐方式 */
enum AlginType {
  /** 上对齐 */
  Top,
  /** 下对齐 */
  Bottom,
  /** 左对齐 */
  Left,
  /** 右对齐 */
  Right,
  /**  居中 */
  Center,
}
Enum(AlginType);

/**
 * 列表
 * 根据cocos_example的listView改动而来
 * @author
 * @example
 *  1.创建cocos的ScrollView组件，添加List，设置List属性即可
 *
 */
@ccclass('ListLayer')
@menu('myComponent/ListLayer')
export class ListLayer extends Component {
  //==================== 属性面板 =========================
  // /**标题选项 */
  // @property({ type: Node, tooltip: '标题项' })
  // public titleRender: Node = null;

  // /**列表选项 */
  // @property({ type: Node, tooltip: '列表项' })
  // public itemRender: Node = null;

  // /**列表选项 */
  // @property({ type: Node, tooltip: '空白项' })
  // public nothingRender: Node = null;
  /**对象池 */
  @property({ type: PoolFactory, tooltip: '对象池' })
  public pool: PoolFactory = null;

  /**排列方式 */
  @property({ type: ListType, tooltip: '排列方式' })
  public type: ListType = ListType.Vertical;

  /**对齐方式 */
  @property({ type: AlginType, tooltip: '对齐方式' })
  public alignHorType: AlginType = AlginType.Center;

  /**对齐方式 */
  @property({ type: AlginType, tooltip: '对齐方式' })
  public alignVerType: AlginType = AlginType.Center;

  /** 标题对齐方式 */
  @property({ type: AlginType, tooltip: '标题对齐方式\n上下滑动时只有左右\n左右滑动时只有上下' })
  public titleAlignType: AlginType = AlginType.Center;

  /** 内容item对齐方式 */
  @property({ type: AlginType, tooltip: '内容item对齐方式\n上下滑动时只有左右\n左右滑动时只有上下' })
  public itemAlignType: AlginType = AlginType.Center;

  /** 空白项对齐方式 */
  @property({ type: AlginType, tooltip: '空白项对齐方式\n上下滑动时只有左右\n左右滑动时只有上下' })
  public nothingAlignType: AlginType = AlginType.Center;

  /** layer之间的距离 */
  @property({
    tooltip: 'layer之间的距离',
  })
  public layerSpace: number = 0;

  /** layer和item之间的距离 */
  @property({
    tooltip: 'layer和item之间的距离',
  })
  public titleSpace: number = 0;

  /** item在行或列上的数量*/
  @property({
    tooltip: 'item在行或列上的数量',
  })
  public numRowOrCol: number = 1;

  /**item之间X间隔 */
  @property({
    tooltip: '列表项X间隔\n注意排列单位数量为1时只有水平滑动时才有效',
  })
  public spaceX: number = 0;

  /**item之间Y间隔 */
  @property({
    tooltip: '列表项Y间隔\n注意排列单位数量为1时只有垂直滑动时才有效',
  })
  public spaceY: number = 0;

  /**上间距 */
  @property({
    tooltip: '上间距',
  })
  public padding_top: number = 0;

  /**下间距 */
  @property({
    tooltip: '下间距',
  })
  public padding_bottom: number = 0;

  /**左间距 */
  @property({
    tooltip: '左间距',
  })
  public padding_left: number = 0;

  /**右间距 */
  @property({
    tooltip: '右间距',
  })
  public padding_right: number = 0;

  /**预留内容的数量 */
  @property({
    tooltip: '预留内容的数量',
  })
  public hideShowNum: number = 1;

  @property({
    type: EventHandler,
    tooltip: '点击事件',
  })
  clickEvent: EventHandler = new EventHandler();

  //====================== 滚动容器 ===============================
  /**列表滚动容器 */
  public scrollView: ScrollView = null;
  /**可活动范围 */
  // private contentParent: UITransform = null;
  private contentParent: Size = null;
  /**scrollView的内容容器 */
  private content: Node = null;
  /**scrollView的内容容器 */
  private contentForm: UITransform = null;

  //======================== 列表项 ===========================
  /** 列表项数据*/
  private itemDataList: Array<ListLayerData> = [];
  /** 上次实例的数量 */
  // private tempItemNum: number = 0;
  /** title的实例数量 */
  private titleSpawnCount: number = 0;
  /** item的实例数量 */
  private itemSpawnCount: number = 0;
  /** 空白项的实例数量 */
  // private nothingSpawnCount: number = 0;
  /**存放列表项实例的数组 */
  private titleList: Array<Node> = [];
  /**存放列表项实例的数组 */
  private itemList: Array<Node> = [];
  /**存放空白项实例的数组 */
  private nothingList: Array<Node> = [];
  /** title的高度 */
  private titleHeight: number = 0;
  /** title的宽度 */
  private titleWidth: number = 0;
  /** item的高度 */
  private itemHeight: number = 0;
  /** item的宽度 */
  private itemWidth: number = 0;
  /** 空白项的高度 */
  private nothingHeight: number = 0;
  /** 空白项的宽度 */
  private nothingWidth: number = 0;
  /**item由于锚点不同的偏移 */
  private titleMoveX: number = 0;
  /**item由于锚点不同的偏移 */
  private titleMoveY: number = 0;
  /**item由于锚点不同的偏移 */
  private itemMoveX: number = 0;
  /**item由于锚点不同的偏移 */
  private itemMoveY: number = 0;
  /**nothing由于锚点不同的偏移 */
  private nothingMoveX: number = 0;
  /**nothing由于锚点不同的偏移 */
  private nothingMoveY: number = 0;

  //======================= 计算参数 ==========================
  /** 现在的第一条数据下标 */
  private topLayerIndex: number = 0;
  /** 现在的最后一条数据下标 */
  private bottomLayerIndex: number = 0;
  /** 记录title的位置 */
  private titlePosList: Array<[titlePos: number, itemPos: number, itemNum: number]> = [];
  /** 记录滑块的位置 */
  private tempContentPos: number = 0;
  /**网格行数 */
  private gridRow: number = 0;
  /**网格列数 */
  private gridCol: number = 0;
  /** 是否填充空白项 */
  private isFillNothing: boolean = false;

  protected onLoad() {
    this.scrollView = this.node.getComponent(ScrollView);
    if (this.type == ListType.Vertical) {
      this.scrollView.horizontal = false;
      this.scrollView.vertical = true;
    } else if (this.type == ListType.Horizontal) {
      this.scrollView.horizontal = true;
      this.scrollView.vertical = false;
    }
    const event = new EventHandler();
    event.target = this.node;
    event.component = 'ListLayer';
    event.handler = 'onScrolling';
    event.customEventData = '';
    this.scrollView.scrollEvents.push(event);

    this.content = this.scrollView.content;
    // this.content.removeAllChildren();
    if (this.clickEvent.target != null) {
      this.content.on(Node.EventType.TOUCH_END, this.onClick, this);
    }
    this.contentForm = this.content.getComponent(UITransform);
    this.contentForm.setAnchorPoint(0, 1);

    const contentParent = this.content.parent.getComponent(UITransform);
    const form = this.node.getComponent(UITransform);
    let ww = form.width - this.padding_left - this.padding_right;
    if (ww <= 0) ww = form.width;
    let hh = form.height - this.padding_top - this.padding_bottom;
    if (hh <= 0) hh = form.height;
    // this.contentParent.setContentSize(ww, hh);
    contentParent.setAnchorPoint(0.5, 0.5);
    this.contentParent = new Size(ww, hh);

    if (this.hideShowNum <= 0) {
      this.hideShowNum = 1;
    }

    //初始化参数
    // this.resetListParam();
  }

  /** 初始化参数 */
  resetListParam() {
    const titleRender = this.pool.pop('titleRender');
    let form = titleRender.getComponent(UITransform);
    this.titleWidth = form.width;
    this.titleHeight = form.height;
    this.titleMoveX = form.width * form.anchorX;
    this.titleMoveY = form.height * form.anchorY - form.height;
    this.pool.push(titleRender);

    const itemRender = this.pool.pop('itemRender');
    form = itemRender.getComponent(UITransform);
    this.itemWidth = form.width;
    this.itemHeight = form.height;
    this.itemMoveX = form.width * form.anchorX;
    this.itemMoveY = form.height * form.anchorY - form.height;

    const nothingRender = this.pool.pop('nothingRender');
    if (nothingRender) {
      form = nothingRender.getComponent(UITransform);
      this.nothingWidth = form.width;
      this.nothingHeight = form.height;
      this.nothingMoveX = form.width * form.anchorX;
      this.nothingMoveY = form.height * form.anchorY - form.height;
      this.isFillNothing = true;
    } else {
      this.isFillNothing = false;
    }

    if (this.type == ListType.Vertical) {
      this.gridCol = Math.floor((this.contentParent.width + this.spaceX) / (this.itemWidth + this.spaceX));
      if (this.gridCol < 1) this.gridCol = 1;
      this.gridRow = Math.ceil((this.contentParent.height + this.spaceY) / (this.itemHeight + this.spaceY));
      if (this.gridRow < 1) this.gridRow = 1;
      let tmpHeight = this.itemHeight;
      if (nothingRender) {
        tmpHeight = this.nothingHeight > tmpHeight ? tmpHeight : this.nothingHeight;
      }
      this.titleSpawnCount = Math.ceil((this.contentParent.height + this.layerSpace) / (this.titleHeight + this.titleSpace + tmpHeight + this.layerSpace)) + this.hideShowNum;
      if (this.titleSpawnCount < 1) this.titleSpawnCount = 1 + this.hideShowNum;
      // this.nothingSpawnCount = this.titleSpawnCount;
      this.itemSpawnCount = this.gridCol * this.gridRow + this.gridCol;
      const temp = this.gridCol * (this.itemWidth + this.spaceX) - this.spaceX;
      if (this.titleWidth > temp) {
        this.contentParent.width = this.titleWidth;
      } else {
        this.contentParent.width = temp;
      }
    } else {
      this.gridRow = Math.floor((this.contentParent.height + this.spaceY) / (this.itemHeight + this.spaceY));
      if (this.gridRow < 1) this.gridRow = 1;
      this.gridCol = Math.ceil((this.contentParent.width + this.spaceX) / (this.itemWidth + this.spaceX));
      if (this.gridCol < 1) this.gridCol = 1;
      let tmpWidth = this.itemWidth;
      if (nothingRender) {
        tmpWidth = this.nothingWidth > tmpWidth ? tmpWidth : this.nothingWidth;
      }
      this.titleSpawnCount = Math.ceil((this.contentParent.width + this.layerSpace) / (this.titleWidth + this.titleSpace + tmpWidth + this.layerSpace)) + this.hideShowNum;
      if (this.titleSpawnCount < 1) this.titleSpawnCount = 1 + this.hideShowNum;
      // this.nothingSpawnCount = this.titleSpawnCount;
      this.itemSpawnCount = this.gridRow * this.gridCol + this.gridRow;
      const temp = this.gridRow * (this.itemHeight + this.spaceY) - this.spaceY;
      if (this.titleHeight > temp) {
        this.contentParent.height = this.titleHeight;
      } else {
        this.contentParent.height = temp;
      }
    }
  }

  /**计算列表的各项参数 */
  private countListParam() {
    const dataLen = this.itemDataList.length;
    if (dataLen <= 0) return;
    // this.bScrolling == false;
    //记录一下是什么方向移动
    this.scrollView.horizontal = false;
    this.scrollView.vertical = false;
    this.scrollView.stopAutoScroll();

    this.titlePosList = [];
    //重新计算滑动节点的变化部分的大小
    let count = 0;
    if (this.type == ListType.Horizontal) {
      let ww = 0;
      for (let i = 0; i < dataLen; i++) {
        const data = this.itemDataList[i];
        let temp = Math.ceil(data.detailsData.length / this.gridRow);
        temp = temp > 0 ? temp : 1;
        this.titlePosList.push([ww, count, count + temp]);
        count += temp;
        ww += this.titleWidth + this.titleSpace + temp * (this.itemWidth + this.spaceX) - this.spaceX + this.layerSpace;
      }
      this.contentForm.width = ww - this.layerSpace;
    } else {
      let hh = 0;
      for (let i = 0; i < dataLen; i++) {
        const data = this.itemDataList[i];
        let temp = Math.ceil(data.detailsData.length / this.gridCol);
        temp = temp > 0 ? temp : 1;
        this.titlePosList.push([hh, count, count + temp]);
        count += temp;
        hh += this.titleHeight + this.titleSpace + temp * (this.itemHeight + this.spaceY) - this.spaceY + this.layerSpace;
      }
      this.contentForm.height = hh - this.layerSpace;
    }

    //内容变化要稍微摆正滑动的节点
    const pos = this.content.getPosition();
    if (this.type == ListType.Horizontal) {
      if (this.contentForm.width <= this.contentParent.width) {
        if (this.alignVerType == AlginType.Top) {
          pos.y = this.contentParent.height / 2;
        } else if (this.alignVerType == AlginType.Bottom) {
          pos.y = this.contentForm.height - this.contentParent.height / 2;
        } else {
          pos.y = this.contentForm.height / 2;
        }
        this.scrollView.enabled = false;
      } else {
        if (pos.x < this.contentParent.width / 2 - this.contentForm.width) {
          pos.x = this.contentParent.width / 2 - this.contentForm.width;
        }
        this.scrollView.enabled = true;
      }
    } else {
      if (this.contentForm.height <= this.contentParent.height) {
        if (this.alignHorType == AlginType.Left) {
          pos.x = -this.contentParent.width / 2;
        } else if (this.alignHorType == AlginType.Right) {
          pos.x = this.contentParent.width / 2 - this.contentForm.width;
        } else {
          pos.x = -this.contentForm.width / 2;
        }
        this.scrollView.enabled = false;
      } else {
        if (pos.y > this.contentForm.height - this.contentParent.height / 2) {
          pos.y = this.contentForm.height - this.contentParent.height / 2;
        }
        this.scrollView.enabled = true;
      }
    }
    this.content.setPosition(pos);

    // this.bScrolling = true;
    // this.scrollView.horizontal = boo;
    // this.scrollView.vertical = !boo;
  }

  /**
   * 更新改变的item
   * @param begin   开始数
   * @param end     结束数
   */
  private itemChangeV(begin: number, end: number, titleIndex: number) {
    const titles = this.titleList;
    const nothings = this.nothingList;
    const dataLen = this.itemDataList.length;
    const titleX = this.calculateTitleX();
    const nothingX = this.calculateNothingX();

    const len = this.titlePosList.length;
    let posData = this.titlePosList[titleIndex];
    let data = this.itemDataList[titleIndex];
    let p = begin - posData[1];
    for (let i = begin; i <= end && titleIndex < len; i++, p++) {
      if (i == posData[2]) {
        titleIndex++;
        posData = this.titlePosList[titleIndex];
        data = this.itemDataList[titleIndex];
        p = i - posData[1];
      }

      const itemLen = data.detailsData.length;
      const itemY = posData[0] + this.titleHeight + this.titleSpace + p * (this.itemHeight + this.spaceY);
      if (posData[1] == i && itemLen < this.gridCol) {
        //当前item内容不够一行
        const itemX = this.calculateItemX(itemLen * (this.itemWidth + this.spaceX) - this.spaceX);
        this.updateItemV(this.itemMoveY - itemY, this.itemMoveX + itemX, i, p, data.detailsData, itemLen);
        continue;
      } else {
        const itemX = this.calculateItemX(this.contentForm.width);
        this.updateItemV(this.itemMoveY - itemY, this.itemMoveX + itemX, i, p, data.detailsData, itemLen);
      }

      //如果这是标题之后的第一条数据，则需要更新标题
      if (posData[1] == i) {
        const temp = titleIndex % this.titleSpawnCount;
        let title = titles[temp];
        let nothing = nothings[temp];
        if (titleIndex >= dataLen) {
          if (title != null) title.active = false;
          if (nothing != null) nothing.active = false;
          continue;
        }
        if (title == null) {
          title = this.getTitle();
          titles[temp] = title;
          this.content.addChild(title);
        }
        const titleRender: ListRender = title.getComponent(ListRender);
        titleRender.itemIndex = titleIndex;
        titleRender.data = data.titleData;
        titleRender.dataChanged();
        title.setPosition(titleX, this.titleMoveY - posData[0]);
        title.active = true;
        if (this.isFillNothing) {
          if (nothing == null) {
            nothing = this.getNothing();
            this.nothingList[temp] = nothing;
            this.content.addChild(nothing);
          }
          const nothingRender: ListRender = nothing.getComponent(ListRender);
          nothingRender.itemIndex = titleIndex;
          nothingRender.data = data.titleData;
          nothingRender.dataChanged();
          nothing.setPosition(nothingX, this.nothingMoveY - posData[0] - this.titleHeight - this.titleSpace);
          nothing.active = true;
        } else {
          if (nothing != null) nothing.active = false;
        }
      }
    }
  }

  private calculateTitleX(): number {
    if (this.titleAlignType == AlginType.Left) {
      return this.titleMoveX;
    } else if (this.titleAlignType == AlginType.Right) {
      return this.titleMoveX + this.contentForm.width - this.titleWidth;
    } else {
      return this.titleMoveX + this.contentForm.width / 2 - this.titleWidth / 2;
    }
  }

  private calculateItemX(itemRowWidth: number): number {
    if (this.itemAlignType == AlginType.Left) {
      return 0;
    } else if (this.itemAlignType == AlginType.Right) {
      return this.contentForm.width - itemRowWidth;
    } else {
      return (this.contentForm.width - itemRowWidth) / 2;
    }
  }

  private calculateNothingX(): number {
    if (this.nothingAlignType == AlginType.Left) {
      return this.nothingMoveX;
    } else if (this.nothingAlignType == AlginType.Right) {
      return this.nothingMoveX + this.contentForm.width - this.nothingWidth;
    } else {
      return this.nothingMoveX + this.contentForm.width / 2 - this.nothingWidth / 2;
    }
  }

  private calculateNothingY(): number {
    if (this.nothingAlignType == AlginType.Top) {
      return this.nothingMoveY;
    } else if (this.nothingAlignType == AlginType.Bottom) {
      return this.nothingMoveY - this.contentForm.height + this.nothingHeight;
    } else {
      return this.nothingMoveY - this.contentForm.height / 2 + this.nothingHeight / 2;
    }
  }

  private updateItemV(titleSpace: number, itemSpace, i: number, j: number, data, itemLen: number) {
    i *= this.gridCol;
    j *= this.gridCol;
    for (let t = 0; t < this.gridCol; t++, i++, j++) {
      const temp = i % this.itemSpawnCount;
      let item = this.itemList[temp];
      if (j >= itemLen) {
        if (item != null) item.active = false;
        break;
      }
      if (item == null) {
        item = this.getItem();
        this.itemList[temp] = item;
        this.content.addChild(item);
      }
      const itemRender: ListRender = item.getComponent(ListRender);
      itemRender.itemIndex = j;
      itemRender.data = data[j];
      itemRender.dataChanged();
      item.setPosition(itemSpace + t * (this.itemWidth + this.spaceX), titleSpace);
      item.active = true;
    }
  }

  /**
   * 更新改变的item
   * @param begin     开始数
   * @param end       结束数
   */
  private itemChangeH(begin: number, end: number, titleIndex: number) {
    const titles = this.titleList;
    const nothings = this.nothingList;
    const dataLen = this.itemDataList.length;
    const titleY = this.calculateTitleY();
    const nothingY = this.calculateNothingY();

    const len = this.titlePosList.length;
    let posData = this.titlePosList[titleIndex];
    let data = this.itemDataList[titleIndex];
    let p = begin - posData[1];
    for (let i = begin; i <= end && titleIndex < len; i++, p++) {
      if (i == posData[2]) {
        titleIndex++;
        posData = this.titlePosList[titleIndex];
        data = this.itemDataList[titleIndex];
        p = i - posData[1];
      }

      const itemLen = data.detailsData.length;
      const itemX = posData[0] + this.titleWidth + this.titleSpace + p * (this.itemWidth + this.spaceX);
      //当前item内容不够一行
      if (posData[1] == i && itemLen < this.gridRow) {
        const itemY = this.calculateItemY(itemLen * (this.itemHeight + this.spaceY) - this.spaceY);
        this.updateItemH(this.itemMoveX + itemX, this.itemMoveY + itemY, i, p, data.detailsData, itemLen);
        continue;
      } else {
        const itemY = this.calculateItemY(this.contentForm.height);
        this.updateItemH(this.itemMoveX + itemX, this.itemMoveY + itemY, i, p, data.detailsData, itemLen);
      }

      //如果这是标题之后的第一条数据，则需要更新标题
      if (posData[1] == i) {
        const temp = titleIndex % this.titleSpawnCount;
        let title = titles[temp];
        let nothing = nothings[temp];
        if (titleIndex >= dataLen) {
          if (title != null) title.active = false;
          if (nothing != null) nothing.active = false;
          continue;
        }
        if (title == null) {
          title = this.getTitle();
          titles[temp] = title;
          this.content.addChild(title);
        }
        const titleRender: ListRender = title.getComponent(ListRender);
        titleRender.itemIndex = titleIndex;
        titleRender.data = data.titleData;
        titleRender.dataChanged();
        title.setPosition(this.titleMoveX + posData[0], titleY);
        title.active = true;
        if (this.isFillNothing) {
          if (nothing == null) {
            nothing = this.getNothing();
            this.nothingList[temp] = nothing;
            this.content.addChild(nothing);
          }
          const nothingRender: ListRender = nothing.getComponent(ListRender);
          nothingRender.itemIndex = titleIndex;
          nothingRender.data = data.titleData;
          nothingRender.dataChanged();
          nothing.setPosition(this.nothingMoveX + posData[0] + this.titleWidth + this.titleSpace, nothingY);
          nothing.active = true;
        } else {
          if (nothing != null) nothing.active = false;
        }
      }
    }
  }

  private calculateTitleY(): number {
    if (this.titleAlignType == AlginType.Top) {
      return this.titleMoveY;
    } else if (this.titleAlignType == AlginType.Bottom) {
      return this.titleMoveY - this.contentForm.height + this.titleHeight;
    } else {
      return this.titleMoveY - this.contentForm.height / 2 + this.titleHeight / 2;
    }
  }

  private calculateItemY(itemColHeight: number): number {
    if (this.itemAlignType == AlginType.Top) {
      return 0;
    } else if (this.itemAlignType == AlginType.Bottom) {
      return itemColHeight - this.contentForm.height;
    } else {
      return -(this.contentForm.height - itemColHeight) / 2;
    }
  }

  private updateItemH(titleSpaceX: number, itemSpaceY, i: number, j: number, data, itemLen: number) {
    i *= this.gridRow;
    j *= this.gridRow;
    for (let t = 0; t < this.gridRow; t++, i++, j++) {
      const temp = i % this.itemSpawnCount;
      let item = this.itemList[temp];
      if (j >= itemLen) {
        if (item != null) item.active = false;
        break;
      }
      if (item == null) {
        item = this.getItem();
        this.itemList[temp] = item;
        this.content.addChild(item);
      }
      const itemRender: ListRender = item.getComponent(ListRender);
      itemRender.itemIndex = j;
      itemRender.data = data[j];
      itemRender.dataChanged();
      item.setPosition(titleSpaceX, itemSpaceY - t * (this.itemWidth + this.spaceX));
      item.active = true;
    }
  }

  private updateItem(begin: number, end: number, titleIndex: number) {
    if (begin > end) return;
    if (this.type == ListType.Vertical) {
      this.itemChangeV(begin, end, titleIndex);
    } else {
      this.itemChangeH(begin, end, titleIndex);
    }
  }

  onScrolling() {
    if ((this.type == ListType.Vertical && this.contentForm.height <= this.contentParent.height) || (this.type == ListType.Horizontal && this.contentForm.width <= this.contentParent.width)) return;
    const nowPos = this.content.getPosition();
    if (this.type == ListType.Vertical) {
      const topIndex = this.getIndexByPos(nowPos.y - this.contentParent.height / 2, this.titleHeight + this.titleSpace, this.itemHeight + this.spaceY);
      const bottomIndex = this.getIndexByPos(nowPos.y + this.contentParent.height / 2, this.titleHeight + this.titleSpace, this.itemHeight + this.spaceY);
      if (this.tempContentPos < nowPos.y) {
        if (this.bottomLayerIndex >= bottomIndex[1]) return;
        const tmp = this.getTitleIndex(this.bottomLayerIndex + 1);
        if (tmp < 0) return;
        this.updateItem(this.bottomLayerIndex + 1, bottomIndex[1], tmp);
        this.topLayerIndex = topIndex[1];
        this.bottomLayerIndex = bottomIndex[1];
      } else {
        if (this.topLayerIndex <= topIndex[1]) return;
        const tmp = this.getTitleIndex(this.topLayerIndex - 1);
        if (tmp < 0) return;
        this.updateItem(topIndex[1], this.topLayerIndex - 1, topIndex[0]);
      }
      this.topLayerIndex = topIndex[1];
      this.bottomLayerIndex = bottomIndex[1];
      this.tempContentPos = nowPos.y;
    } else {
      const topIndex = this.getIndexByPos(this.contentParent.width / 2 - nowPos.x, this.titleWidth + this.titleSpace, this.itemWidth + this.spaceX);
      const bottomIndex = this.getIndexByPos(-nowPos.x - this.contentParent.width / 2, this.titleWidth + this.titleSpace, this.itemWidth + this.spaceX);
      if (this.tempContentPos > nowPos.x) {
        if (this.bottomLayerIndex >= bottomIndex[1]) return;
        const tmp = this.getTitleIndex(this.bottomLayerIndex + 1);
        if (tmp < 0) return;
        this.updateItem(this.bottomLayerIndex + 1, bottomIndex[1], tmp);
      } else {
        if (this.topLayerIndex <= topIndex[1]) return;
        const tmp = this.getTitleIndex(this.topLayerIndex - 1);
        if (tmp < 0) return;
        this.updateItem(topIndex[1], this.topLayerIndex - 1, topIndex[0]);
      }
      this.topLayerIndex = topIndex[1];
      this.bottomLayerIndex = bottomIndex[1];
      this.tempContentPos = nowPos.x;
    }
  }

  private getTitleIndex(itemIndex: number): number {
    const len = this.titlePosList.length;
    let titleIndex = 0;
    for (; titleIndex < len; titleIndex++) {
      const tmp = this.titlePosList[titleIndex];
      if (itemIndex >= tmp[1] && itemIndex < tmp[2]) {
        break;
      }
    }
    return titleIndex >= len ? -1 : titleIndex;
  }

  private getIndexByPos(pos: number, titleSpace, itemSpace) {
    const len = this.titlePosList.length - 1;
    let titleIndex = 0;
    for (; titleIndex < len; titleIndex++) {
      if (pos >= this.titlePosList[titleIndex][0] && pos < this.titlePosList[titleIndex + 1][0]) {
        break;
      }
    }
    const tempPos = this.titlePosList[titleIndex];
    let itemIndex = tempPos[1];
    let pp = tempPos[0] + titleSpace;
    if (pos > pp) {
      pp = pos - pp;
      itemIndex += Math.floor(pp / itemSpace);
    }
    return [titleIndex, itemIndex];
  }

  /**
   * 列表数据 (列表数据复制使用，如果列表数据改变，则需要重新设置一遍数据)
   * @param itemDataList item数据列表
   */
  public setData(itemDataList: Array<ListLayerData>) {
    this.itemDataList = itemDataList;
    if (this.node.active) {
      this.countListParam();
      this.topLayerIndex = 0;
      const tmp = this.getIndexByPos(this.contentParent.height, this.titleHeight + this.titleSpace, this.itemHeight + this.spaceY);
      this.bottomLayerIndex = tmp[1];
      //初始化时多更新 1 项
      // const end = { title: this.bottomLayerIndex.title, item: this.bottomLayerIndex.item };
      // this.updateIndexAdd(end);
      this.updateItem(this.topLayerIndex, this.bottomLayerIndex, 0);
      this.startDoSomething();
      if (this.type == ListType.Vertical) {
        this.scrollView.horizontal = false;
        this.scrollView.vertical = true;
      } else if (this.type == ListType.Horizontal) {
        this.scrollView.horizontal = true;
        this.scrollView.vertical = false;
      }
    }
  }

  // public judgeItemData(...param) {
  //   if (this.inputFun == null) return;
  //   if (!this.node.active) {
  //     this.node.active = true;
  //   }
  //   if (param.length > 0) {
  //     const arr = [];
  //     this.itemDataListAll.forEach((element) => {
  //       if (this.inputFun(element, param)) arr.push(element);
  //     });
  //     this.itemDataList = arr;
  //   } else {
  //     this.itemDataList = this.itemDataListAll;
  //   }
  //   this.updateContent();
  // }

  /**获取一个列表项 */
  private getTitle() {
    return this.pool.pop('titleRender');
  }

  /**获取一个列表项 */
  private getItem() {
    return this.pool.pop('itemRender');
  }

  /**获取一个空白项 */
  private getNothing() {
    return this.pool.pop('nothingRender');
  }

  /**获取item在scrollView的局部坐标 */
  // private getPositionInView(item: Node) {
  //   const worldPos = item.parent.getComponent(UITransform).convertToWorldSpaceAR(item.position);
  //   const viewPos = this.scrollView.node.getComponent(UITransform).convertToNodeSpaceAR(worldPos);
  //   return viewPos;
  // }

  private onClick(event: EventTouch) {
    const clickPos = event.getUILocation();
    const pos = this.contentForm.convertToNodeSpaceAR(v3(clickPos.x, clickPos.y));
    let posIndex;
    if (this.type == ListType.Vertical) {
      posIndex = this.getIndexByPos(-pos.y, this.titleHeight + this.titleSpace, this.itemHeight + this.spaceY);
    } else {
      posIndex = this.getIndexByPos(pos.x, this.titleWidth + this.titleSpace, this.itemHeight + this.spaceY);
    }
    const posData = this.titlePosList[posIndex[0]];
    const tmp = posIndex[1] - posData[1];
    if (tmp < 0) return;
    const num = this.itemDataList[posIndex[0]].detailsData.length;
    if (this.type == ListType.Vertical) {
      const posY = -pos.y - posData[0] - this.titleHeight - this.titleSpace + tmp * (this.itemHeight + this.spaceY);
      if (posY < 0) return;
      const itemIndex = tmp * this.gridCol;
      if (itemIndex >= num) return;
      const numCol = num - itemIndex > this.gridCol ? this.gridCol : num - itemIndex;
      const posX = pos.x - this.calculateItemX(numCol * (this.itemWidth + this.spaceX) - this.spaceX);
      if (posX < 0 || posX % (this.itemWidth + this.spaceX) > this.itemWidth) return;
      const sp = this.clickEvent.target.getComponent(this.clickEvent._componentName);
      sp[this.clickEvent.handler].call(sp, event, this.itemDataList[posIndex[0]].detailsData[itemIndex + Math.floor(posX / (this.itemWidth + this.spaceX))], this.clickEvent.customEventData);
    } else {
      const posX = pos.x - posData[0] - this.titleWidth - this.titleSpace + tmp * (this.itemWidth + this.spaceX);
      if (posX < 0) return;
      const itemIndex = tmp * this.gridRow;
      if (itemIndex >= num) return;
      const numRow = num - itemIndex > this.gridRow ? this.gridRow : num - itemIndex;
      const posY = -pos.y + this.calculateItemY(numRow * (this.itemHeight + this.spaceY) - this.spaceY);
      if (posY < 0 || posY % (this.itemHeight + this.spaceY) > this.itemHeight) return;
      const sp = this.clickEvent.target.getComponent(this.clickEvent._componentName);
      sp[this.clickEvent.handler].call(sp, event, this.itemDataList[posIndex[0]].detailsData[itemIndex + Math.floor(posY / (this.itemHeight + this.spaceY))], this.clickEvent.customEventData);
    }
  }

  /**获取列表数据 */
  public getListData() {
    return this.itemDataList;
  }

  public startDoSomething() {
    // const items = this.itemList;
    // const dataLen = this.itemDataList.length;
    // let j;
    // if (this.scrollView.vertical) {
    //   j = this.nowContentPos * this.gridCol;
    // } else {
    //   j = this.nowContentPos * this.gridRow;
    // }
    // const end = j + this.spawnCount;
    // for (; j < end; j++) {
    //   const temp = j % this.spawnCount;
    //   let item = items[temp];
    //   if (j >= dataLen) {
    //     if (item != null) {
    //       item.active = false;
    //       continue;
    //     } else {
    //       break;
    //     }
    //   }
    //   if (item == null) {
    //     item = this.getItem();
    //     items[temp] = item;
    //     this.content.addChild(item);
    //   }
    //   const itemRender: ListItem = item.getComponent(ListItem);
    //   item.active = true;
    //   itemRender.startDo();
    // }
  }

  /**销毁 */
  public onDestroy() {
    this.onDisable();
  }

  public onDisable() {
    this.titleList.forEach((ele) => {
      this.pool.push(ele);
    });
    this.itemList.forEach((ele) => {
      this.pool.push(ele);
    });
    this.nothingList.forEach((ele) => {
      this.pool.push(ele);
    });
    this.titleList.length = 0;
    this.itemList.length = 0;
    this.nothingList.length = 0;
    this.topLayerIndex = 0;
    this.bottomLayerIndex = 0;
    this.tempContentPos = 0;
    // this.content.setPosition(0, 0);
    //清理列表数据
    this.itemDataList.length = 0;
  }
}
